package xcache

import (
	"encoding/json"
	"fmt"
	"time"
)

// 设置Key的值
//
//	key	下标
//	val	值
//	t	延时删除时间
func SetExt(key, val string, t time.Duration) error {
	_default.CacheSync.Store(key, val) // 存储到运行内存中
	// 定时移除
	go func() {
		if t.Hours() > 12 {
			time.Sleep(time.Hour * 12)
			_default.CacheSync.Delete(key)
		} else {
			time.Sleep(t)
			_default.CacheSync.Delete(key)
		}
	}()
	// 如果redis地址为空，则直接使用程序缓存
	if _default.Hosts == "" {
		return nil
	}
	open()
	defer close()
	if _default.Connect == nil {
		return nil
	}
	defer panic_recover("set")
	// 设置redis缓存
	if _, err := _default.Connect.Do("SET", key, val); err != nil {
		return errorFunc("数据存储报错", err)
	}
	// 设置redis有效期
	// Redis不支持设置小数的有效期，所以此处一旦出现浮点数容易报错，需要使用int进行格式化一下
	if _, err := _default.Connect.Do("EXPIRE", key, int(t.Seconds())); err != nil {
		return errorFunc("数据有效期设置报错", err)
	}
	return nil
}

// 设置Key的值
//
//	key	下标
//	val	值
func Set(key, val string) error {
	return SetExt(key, val, _default.DefaultTime)
}

// 设置数字类型缓存，避免使用时再进行fmt.Sprintf转化(因any类型可能为多种数字类型，所以此处使用fmt进行转化)
// 使用SetNumber存储，读取时也只能使用GetString进行读取，然后再通过xstring.Toxxxx进行转化【或者使用json.Number进行转化】
//
//	key	缓存下标
//	val	缓存值
func SetNumber(key string, val any) error {
	switch v := val.(type) {
	case float32, float64:
		return Set(key, fmt.Sprintf("%f", v))
	case int8, uint8, int16, uint16, int32, uint32, int, uint, int64, uint64:
		return Set(key, fmt.Sprintf("%d", v))
	case string:
		return Set(key, v)
	default:
		return SetStruct(key, v)
	}
}

// 设置结构体
//
//	key	缓存的key名称
//	val	设置的缓存值类型，使用json串行化进行解析存储
func SetStruct(key string, val any) error {
	str, err := json.Marshal(val)
	if err != nil {
		return err
	}
	// 默认设置2小时缓存
	return Set(key, string(str))
}

// 设置结构体
//
//	key	缓存的key名称
//	val	设置的缓存值类型，使用json串行化进行解析存储
//	t	缓存时间
func SetStructExt(key string, val any, t time.Duration) error {
	str, err := json.Marshal(val)
	if err != nil {
		return err
	}
	// 默认设置2小时缓存
	return SetExt(key, string(str), t)
}
